package cn.wlinker.video.monitor.config;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.ContentType;
import cn.hutool.log.StaticLog;
import cn.wlinker.video.monitor.domain.R;
import lombok.SneakyThrows;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 控制器拦截器
 *
 * @author gxsjx
 * @version 1.0
 * @date 2022/8/12
 */
@Aspect
@Component
@ConditionalOnProperty(value = "auth.enabled", havingValue = "true")
public class ControllerAspect {

    @Value("${auth.token}")
    private String targetToken;

    @Value("${auth.tokenKey}")
    private String tokenKey;

    @Value("${auth.enabled}")
    private Boolean authEnabled;

    /**
     * 调用controller包下的任意类的任意方法时均会调用此方法
     */
    @Around("execution(* cn.wlinker.video.monitor.controller.*.*(..))")
    public Object run1(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取方法参数值数组
        Object[] args = joinPoint.getArgs();
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        assert sra != null;
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader(tokenKey);
        String paramToken = request.getParameter(tokenKey);
        if (Boolean.TRUE.equals(authEnabled)) {
            if (!ObjectUtil.equal(token, targetToken) && !ObjectUtil.equal(paramToken, targetToken)) {
                return sendResponse(sra, "令牌有误缺失");
            }
        }
        //动态修改其参数
        //注意，如果调用joinPoint.proceed()方法，则修改的参数值不会生效，必须调用joinPoint.proceed(Object[] args)
        try {
            //如果这里不返回result，则目标对象实际返回值会被置为null
            return joinPoint.proceed(args);
        } catch (UnsupportedOperationException unsupportedOperationException) {
            return sendResponse(sra, 23, "平台或设备不支持相关功能");
        } catch (Exception exception) {
            StaticLog.error(exception,"拦截器异常");
            return sendResponse(sra, exception.toString());
        }
    }

    @SneakyThrows
    Object sendResponse(ServletRequestAttributes sra, String msg) {
        return sendResponse(sra, -1, msg);
    }

    @SneakyThrows
    Object sendResponse(ServletRequestAttributes sra, int code, String msg) {
        HttpServletResponse response = sra.getResponse();
        assert response != null;
        response.setContentType(ContentType.JSON.toString());
        response.setCharacterEncoding(CharsetUtil.defaultCharsetName());
        return new R<String>(code, msg);
    }
}
